﻿/***************************************************************************
 *   Copyright (C) 2014-2015 by Rodolfo Conde Martínez                     *
 *   rcm@gmx.co.uk                                                         *
 ***************************************************************************/



using System;
using System.Text;
using System.Data;
using System.Data.Common;

using OBTUtils.Data.SQL;



namespace OBTUtils.Data.Java
{
	/// <summary>
	/// All supported Java DB entities managers
	/// </summary>
	public enum JavaDBEntitiesManagers {
		/// <summary>
		/// No entitites support
		/// </summary>
		none,
		
		/// <summary>
		/// ORM Lite support
		/// </summary>
		ormlite
	}
	
	
	/// <summary>
	/// 
	/// </summary>
	/// 
	/// <remarks>\author \rodolfo</remarks>
	public class POJOGenerator : GenericDB2CodeGenerator
	{
		/// <summary>
		/// Indicates how to generate additional code in the POJOs
		/// so that they are suitable for use with the specified
		/// Java entities manager
		/// </summary>
		private JavaDBEntitiesManagers entitysupport;
		
		/// <summary>
		/// Gets or sets a value that indicates how to generate additional code in the POJOs
		/// so that they are suitable for use with the specified
		/// Java entities manager
		/// </summary>
		public JavaDBEntitiesManagers Entitysupport {
			get { return entitysupport; }
			set { entitysupport = value; }
		}
		
		
		/// <summary>
		/// Constructor
		/// </summary>
		/// <param name="providergenericname">ADO.Net database provider's
		/// invariant name</param>
		/// <param name="dbconnectionstring">The connection string to be used</param>
		/// <param name = "entitysupport">This parameter indicates which type of entity database support
		/// must be programmed into the generated POJOs classes</param>
		public POJOGenerator(string providergenericname,
		                     string dbconnectionstring, JavaDBEntitiesManagers entitysupport)
			: base(DbProviderFactories.GetFactory(providergenericname),
			       dbconnectionstring)
		{
			this.entitysupport = entitysupport;
		}
		
		
		private string generateNewPOJO(DataTable thetable) {
			StringBuilder conscadena = new StringBuilder();
			
			conscadena.AppendLine("/***********************************" +
			                      "****************************************");
			conscadena.AppendLine(" *   FILE AUTO GENERATED by POJOGenerator " +
			                      "                                 *");
			conscadena.AppendLine(" *                                         " +
			                      "                                *");
			conscadena.AppendLine(" ******************************************" +
			                      "*********************************/");
			
			conscadena.AppendLine();
			conscadena.AppendLine();
			
			conscadena.AppendLine("package org.obtutils.data.entitites;");
			
			conscadena.AppendLine();
			conscadena.AppendLine();
			
			if (entitysupport == JavaDBEntitiesManagers.ormlite) {
				conscadena.AppendLine("import com.j256.ormlite.field.DatabaseField;");
				conscadena.AppendLine("import com.j256.ormlite.table.DatabaseTable;");
				
				conscadena.AppendLine();
				conscadena.AppendLine();
			}
			
			conscadena.AppendLine("/**");
			conscadena.AppendLine(" *");
			conscadena.AppendFormat(" * A class representing the table {0}", thetable.TableName).AppendLine();
			conscadena.AppendLine(" *");
			conscadena.AppendLine(" */");
			
			if (entitysupport == JavaDBEntitiesManagers.ormlite)
				conscadena.AppendFormat("@DatabaseTable(tableName = \"{0}\")", thetable.TableName).AppendLine();
			
			conscadena.AppendFormat("public class {0} {{", thetable.TableName).AppendLine();
			
			foreach (DataColumn column in thetable.Columns) {
				conscadena.AppendFormat("\t/// Represents the column named {0}", column.ColumnName).AppendLine();
				
				if (entitysupport == JavaDBEntitiesManagers.ormlite)
					conscadena.AppendFormat("\t@DatabaseField(columnName = \"{0}\")",
					                        column.ColumnName).AppendLine();
				
				conscadena.AppendFormat("\tprivate {0} {1};",
				                        getJavaTypeForColumn(column),
				                        column.ColumnName).AppendLine();
				
				conscadena.AppendLine();
			}
			
			conscadena.AppendLine();
			conscadena.AppendLine();
			
			conscadena.AppendLine("\t/**");
			conscadena.AppendLine("\t *");
			conscadena.AppendLine("\t * Constructor");
			conscadena.AppendLine("\t *");
			conscadena.AppendLine("\t */");
			conscadena.AppendFormat("\tpublic {0}() {{ }}", thetable.TableName).AppendLine();
			
			conscadena.AppendLine();
			conscadena.AppendLine();
			
			foreach (DataColumn column in thetable.Columns) {
				string propertyname;
				
				if (column.ColumnName.Length > 1)
					propertyname = Char.ToUpper(column.ColumnName[0]).ToString() + column.ColumnName.Substring(1);
				else
					propertyname = column.ColumnName.ToUpper();
				
				conscadena.AppendLine("\t/**");
				conscadena.AppendLine("\t *");
				conscadena.AppendFormat("\t * Gets the value of the column named {0}", column.ColumnName).AppendLine();
				conscadena.AppendLine("\t *");
				conscadena.AppendFormat("\t * @return The value of the column named {0}",
				                        column.ColumnName).AppendLine();
				conscadena.AppendLine("\t *");
				conscadena.AppendLine("\t */");
				conscadena.AppendFormat(
					"\tpublic {0} get{1}() {{",
					getJavaTypeForColumn(column),
					propertyname
				).AppendLine();
				
				conscadena.AppendFormat("\t\treturn {0};", column.ColumnName).AppendLine();
				
				conscadena.AppendLine("\t}");
				
				conscadena.AppendLine();
				
				conscadena.AppendLine("\t/**");
				conscadena.AppendLine("\t *");
				conscadena.AppendFormat("\t * Sets the value of the column named {0}", column.ColumnName).AppendLine();
				conscadena.AppendLine("\t *");
				conscadena.AppendLine("\t * @param thevalue The new value");
				conscadena.AppendLine("\t *");
				conscadena.AppendLine("\t */");
				conscadena.AppendFormat(
					"\tpublic void set{1}({0} thevalue) {{",
					getJavaTypeForColumn(column),
					propertyname
				).AppendLine();
				
				conscadena.AppendFormat("\t\t{0} = thevalue;", column.ColumnName).AppendLine();
				
				conscadena.AppendLine("\t}");
				
				conscadena.AppendLine();
			}
			
			if (entitysupport == JavaDBEntitiesManagers.ormlite) {
				int ncolumns = 0;
				
				foreach (DataColumn column in thetable.Columns) {
					string propertyname;
					
					if (column.ColumnName.Length > 1)
						propertyname = Char.ToUpper(column.ColumnName[0]).ToString() + column.ColumnName.Substring(1);
					else
						propertyname = column.ColumnName.ToUpper();
					
					conscadena.AppendLine("\t/**");
					conscadena.AppendLine("\t *");
					conscadena.AppendFormat("\t * Gets the database name of the column named {0}",
					                        column.ColumnName).AppendLine();
					conscadena.AppendLine("\t *");
					conscadena.AppendFormat("\t * @return The name of the column").AppendLine();
					conscadena.AppendLine("\t *");
					conscadena.AppendLine("\t */");
					conscadena.AppendFormat(
						"\tpublic {0} get{1}DBName() {{",
						getJavaTypeForColumn(column),
						propertyname
					).AppendLine();
					
					conscadena.AppendFormat("\t\treturn \"{0}\";", column.ColumnName).AppendLine();
					
					conscadena.AppendLine("\t}");
					
					if (++ncolumns < thetable.Columns.Count)
						conscadena.AppendLine();
				}
			}
			
			conscadena.AppendLine("}");
			
			return conscadena.ToString();
		}
		
		private string getJavaTypeForColumn(DataColumn column) {
			string returnvalue, dotnettype;
			
			dotnettype = column.DataType.ToString().Replace("System.", String.Empty);
			
			switch (dotnettype) {
				case "Boolean":
					returnvalue = "boolean";
					break;
				case "Int32":
					returnvalue = "int";
					break;
				case "Int64":
					returnvalue = "long";
					break;
				case "Int16":
					returnvalue = "short";
					break;
				case "Double":
					returnvalue = "double";
					break;
				case "Float":
					returnvalue = "float";
					break;
				case "DateTime":
					returnvalue = "Date";
					break;
				default:
					returnvalue = dotnettype;
					break;
			}
			
			return returnvalue;
		}
		
		
		public string generatePOJO(string thetable) {
			return generateCode(thetable, generateNewPOJO);
		}
	}
}
